package framework.view.components.container
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;

import framework.core.ComponentBuilder;
import framework.view.components.IComponent;
import framework.view.components.container.layout.LayoutBase;
import framework.view.components.container.navigation.NavigatorBase;
import framework.view.events.RepeaterEvent;

import mx.utils.ArrayUtil;

[Event(name="repeaterUpdated", type="framework.view.events.RepeaterEvent")]
[Event(name="repeaterSelected", type="framework.view.events.RepeaterEvent")]
[Event(name="repeaterReadyToSelect", type="framework.view.events.RepeaterEvent")]

/**
 * Repeater
 * @author jliang
 * 
 */
public class Repeater extends Sprite implements IComponent
{
	//==========================================================================
	//  Constructor
	//==========================================================================
	public function Repeater()
	{
		_layout.container = this;
        this.addEventListener(RepeaterEvent.REPEATER_READY_TO_SELECT, readyToSelectHandler);
		super();
	}
	//==========================================================================
	//  Properties
	//==========================================================================
	protected var _layout:LayoutBase = new LayoutBase();

	public function get layout():LayoutBase
	{
		return _layout;
	}

	public function set layout(value:LayoutBase):void
	{
		_layout = value;
		_layout.container = this;
	}
	
	protected var _navigator:NavigatorBase;

	public function get navigator():NavigatorBase
	{
		return _navigator;
	}

	public function set navigator(value:NavigatorBase):void
	{
		_navigator = value;
		_navigator.target = this;
	}
	
	protected var _itemRenderClass:Class;
	
	/**
	 * The custom item renderer for the control.
	 */
	public function get itemRenderClass():Class
	{
		return _itemRenderClass;
	}
	
	public function set itemRenderClass(value:Class):void
	{
		_itemRenderClass = value;
	}
	
	protected var _data:*;

	public function get data():*
	{
		return _data;
	}

	public function set data(value:*):void
	{
		if (value is Array || Vector.<*>)
		{
			_data = value;
		}
		else
		{
			_data = ArrayUtil.toArray(value);
		}
	}
	
	protected var _items:Array = [];

	public function get items():Array
	{
		return _items;
	}

	public function set items(value:Array):void
	{
		_items = value;
	}
    
    protected var _selectedIndex:int = -1;
    
    public function set selectedIndex(value:int):void
    {
        var evt:RepeaterEvent = new RepeaterEvent(RepeaterEvent.REPEATER_READY_TO_SELECT, true, true);
        evt.selectIndex = value;
        dispatchEvent(evt);
    }
    
    public function get selectedIndex():int
    {
        return _selectedIndex;
    }
	
	public function setSelectedIndex(value:int):void
	{
		_selectedIndex = value;
	}

	//==========================================================================
	//  Public methods
	//==========================================================================
	public function update():void
	{
		removeAll();
		
		if(data)
		{
			_items = [];			
			var dataLen:uint = _data.length;			
			for(var i:uint = 0; i < dataLen; i++)
			{
				var item:DisplayObject = ComponentBuilder.create(itemRenderClass);	
				if (item is IRender) 
				{	
                    item.addEventListener(Event.SELECT, itemSelectedHandler);
					IRender(item).index = i;
					IRender(item).data = _data[i];
				}
				_items.push(item);
			}
			layout.addItems(_items);
		}
		this.dispatchEvent(new RepeaterEvent(RepeaterEvent.REPEATER_UPDATED, true));
	}
	
	public function removeAll():void
	{
        for each (var item:DisplayObject in _items)
        {
            item.removeEventListener(Event.SELECT, itemSelectedHandler);
        }
		layout.removeAll();
		_items = [];
	}
	
	public function commitProperty():void
	{
		if (data)
		{
			update();
		}
	}
	
	public function dispose():void
	{
        removeAll();
        this.removeEventListener(RepeaterEvent.REPEATER_READY_TO_SELECT, readyToSelectHandler);
		if (layout)
		{
			layout.dispose();
		}
		if (navigator)
		{
			navigator.dispose();
		}
	}
	
	public function appendChild(value:DisplayObject):DisplayObject
	{
		return appendChildAt(value, _items.length);
	}
	
	public function appendChildAt(value:DisplayObject, index:int):DisplayObject
	{
		if (!_items) _items = [];
        
        if (value is IRender) value.addEventListener(Event.SELECT, itemSelectedHandler);
                    
		if (_items[index] != null)
		{
			var tempArray:Array = _items.splice(index);
			_items.push(value);
			_items = _items.concat(tempArray);
			if (value is IRender)
			{
				for (var i:int = 0; i < _items.length; i++)
				{
					IRender(_items[i]).index = i;
				}	
			}
		}
		else
		{
			if (value is IRender) IRender(value).index = index;
			_items[index] = value;
		}
		layout.addItems(_items);
		this.dispatchEvent(new RepeaterEvent(RepeaterEvent.REPEATER_UPDATED, true));
		this.dispatchEvent(new Event(Event.RESIZE));
		return value;
	}
	
	public function deleteChild(value:DisplayObject, isDispose:Boolean = true):DisplayObject
	{		
		if (!_items) return null;
		
		var index:int = -1;
		for (var i:int = 0; i < _items.length; i++)
		{
			if (_items[i] == value)
			{
				index = i;
				break;
			}
		}
		if (index < 0) return null;
		
		if (isDispose)
		{
			value.removeEventListener(Event.SELECT, itemSelectedHandler);
			if (value is IComponent)
			{
				IComponent(value).dispose();
			}
			if (value.parent)
			{
				value.parent.removeChild(value);
			}
		}
		
		_items.splice(index, 1);
		
		for (var n:int = 0; n < _items.length; n++)
		{
			if (!(_items[n] is IRender)) continue;
			var render:IRender = IRender(_items[n]);
			render.index = n;
		}
		
		layout.addItems(_items);
		this.dispatchEvent(new RepeaterEvent(RepeaterEvent.REPEATER_UPDATED, true));
		this.dispatchEvent(new Event(Event.RESIZE));
		
		return value;
	}
	
	override public function addChild(child:DisplayObject):DisplayObject
	{
		super.addChild(child);
		this.dispatchEvent(new Event(Event.RESIZE));
		return child;
	}
	
	override public function removeChild(child:DisplayObject):DisplayObject
	{
		super.removeChild(child);
		this.dispatchEvent(new Event(Event.RESIZE));
		return child;
	}
    
    protected function itemSelectedHandler(event:Event):void
    {
        this.selectedIndex = IRender(event.target).index;
    }
    
    protected function readyToSelectHandler(event:RepeaterEvent):void
    {
        for (var i:int = 0; i < _items.length; i++)
        {
            var item:* = _items[i];
            if (item is IRender)
            {
                if (event.selectIndex == i)
                {
                    IRender(item).selected = true;
                    _selectedIndex = i;
                    var evt:RepeaterEvent = new RepeaterEvent(RepeaterEvent.REPEATER_SELECTED, true);
                    evt.render = item;
                    dispatchEvent(evt);
                }
                else
                {
                    IRender(item).selected = false;
                }
            }
        }
    }
}
}